/*
 * absyn.c - Abstract Syntax Functions. Most functions create an instance of an
 *           abstract syntax rule.
 */

#include "util.h"
#include "symbol.h" /* symbol table data structures */
#include "absyn.h"  /* abstract syntax data structures */

A_var A_SimpleVar(A_pos pos, S_symbol sym)
{
  A_var p = checked_malloc(sizeof(*p));
  p->kind=A_simpleVar;
  p->pos=pos;
  p->u.simple=sym;
  return p;
}

A_var A_FieldVar(A_pos pos, A_var var, S_symbol sym)
{
  A_var p = checked_malloc(sizeof(*p));
  p->kind=A_fieldVar;
  p->pos=pos;
  p->u.field.var=var;
  p->u.field.sym=sym;
  return p;
}

A_var A_SubscriptVar(A_pos pos, A_var var, A_exp exp)
{
  A_var p = checked_malloc(sizeof(*p));
  p->kind=A_subscriptVar;
  p->pos=pos;
  p->u.subscript.var=var;
  p->u.subscript.exp=exp;
  return p;
}


A_exp A_VarExp(A_pos pos, A_var var)
{
  A_exp p = checked_malloc(sizeof(*p));
  p->kind=A_varExp;
  p->pos=pos;
  p->u.var=var;
  return p;
}

A_exp A_NilExp(A_pos pos)
{
  A_exp p = checked_malloc(sizeof(*p));
  p->kind=A_nilExp;
  p->pos=pos;
  return p;
}

A_exp A_IntExp(A_pos pos, int i)
{
  A_exp p = checked_malloc(sizeof(*p));
  p->kind=A_intExp;
  p->pos=pos;
  p->u.intt=i;
  return p;
}

A_exp A_StringExp(A_pos pos, string s)
{
  A_exp p = checked_malloc(sizeof(*p));
  p->kind=A_stringExp;
  p->pos=pos;
  p->u.stringg=s;
  return p;
}

A_exp A_CallExp(A_pos pos, S_symbol func, A_expList args)
{
  A_exp p = checked_malloc(sizeof(*p));
  p->kind=A_callExp;
  p->pos=pos;
  p->u.call.func=func;
  p->u.call.args=args;
  return p;
}

A_exp A_OpExp(A_pos pos, A_oper oper, A_exp left, A_exp right)
{
  A_exp p = checked_malloc(sizeof(*p));
  p->kind=A_opExp;
  p->pos=pos;
  p->u.op.oper=oper;
  p->u.op.left=left;
  p->u.op.right=right;
  return p;
}

A_exp A_RecordExp(A_pos pos, S_symbol typ, A_efieldList fields)
{
  A_exp p = checked_malloc(sizeof(*p));
  p->kind=A_recordExp;
  p->pos=pos;
  p->u.record.typ=typ;
  p->u.record.fields=fields;
  return p;
}

A_exp A_SeqExp(A_pos pos, A_expList seq)
{
  A_exp p = checked_malloc(sizeof(*p));
  p->kind=A_seqExp;
  p->pos=pos;
  p->u.seq=seq;
  return p;
}

A_exp A_AssignExp(A_pos pos, A_var var, A_exp exp)
{
  A_exp p = checked_malloc(sizeof(*p));
  p->kind=A_assignExp;
  p->pos=pos;
  p->u.assign.var=var;
  p->u.assign.exp=exp;
  return p;
}

A_exp A_IfExp(A_pos pos, A_exp test, A_exp then, A_exp elsee)
{
  A_exp p = checked_malloc(sizeof(*p));
  p->kind=A_ifExp;
  p->pos=pos;
  p->u.iff.test=test;
  p->u.iff.then=then;
  p->u.iff.elsee=elsee;
  return p;
}

A_exp A_WhileExp(A_pos pos, A_exp test, A_exp body)
{
  A_exp p = checked_malloc(sizeof(*p));
  p->kind=A_whileExp;
  p->pos=pos;
  p->u.whilee.test=test;
  p->u.whilee.body=body;
  return p;
}

A_exp A_ForExp(A_pos pos, S_symbol var, A_exp lo, A_exp hi, A_exp body)
{
  A_exp p = checked_malloc(sizeof(*p));
  p->kind=A_forExp;
  p->pos=pos;
  p->u.forr.var=var;
  p->u.forr.lo=lo;
  p->u.forr.hi=hi;
  p->u.forr.body=body;
  p->u.forr.escape=TRUE;
  return p;
}

A_exp A_BreakExp(A_pos pos)
{
  A_exp p = checked_malloc(sizeof(*p));
  p->kind=A_breakExp;
  p->pos=pos;
  return p;
}

A_exp A_LetExp(A_pos pos, A_decList decs, A_expList body)
{
  A_exp p = checked_malloc(sizeof(*p));
  p->kind=A_letExp;
  p->pos=pos;
  p->u.let.decs=decs;
  p->u.let.body=body;
  return p;
}

A_exp A_ArrayExp(A_pos pos, S_symbol typ, A_exp size, A_exp init)
{
  A_exp p = checked_malloc(sizeof(*p));
  p->kind=A_arrayExp;
  p->pos=pos;
  p->u.array.typ=typ;
  p->u.array.size=size;
  p->u.array.init=init;
  return p;
}

A_dec A_VarDec(A_pos pos, S_symbol var, S_symbol typ, A_exp init)
{
  A_dec p = checked_malloc(sizeof(*p));
  p->kind=A_varDec;
  p->pos=pos;
  p->u.var.var=var;
  p->u.var.typ=typ;
  p->u.var.init=init;
  p->u.var.escape=TRUE;
  return p;
}

A_ty A_NameTy(S_symbol name)
{
  A_ty p = checked_malloc(sizeof(*p));
  p->kind=A_nameTy;
  p->u.name=name;
  return p;
}

A_ty A_RecordTy(A_fieldList record)
{
  A_ty p = checked_malloc(sizeof(*p));
  p->kind=A_recordTy;
  p->u.record=record;
  return p;
}

A_ty A_ArrayTy(S_symbol array)
{
  A_ty p = checked_malloc(sizeof(*p));
  p->kind=A_arrayTy;
  p->u.array=array;
  return p;
}

A_field A_Field(A_pos pos, S_symbol name, S_symbol typ)
{
  A_field p = checked_malloc(sizeof(*p));
  p->pos=pos;
  p->name=name;
  p->typ=typ;
  p->escape=TRUE;
  return p;
}

A_fieldList A_FieldList(A_field head, A_fieldList tail)
{
  A_fieldList p = checked_malloc(sizeof(*p));
  p->head=head;
  p->tail=tail;
  return p;
}

A_expList A_ExpList(A_exp head, A_expList tail)
{
  A_expList p = checked_malloc(sizeof(*p));
  p->head=head;
  p->tail=tail;
  return p;
}

A_dec A_Fundec(A_pos pos, S_symbol name, A_fieldList params, S_symbol result, A_exp body)
{
  A_dec p = checked_malloc(sizeof(*p));

  p->kind = A_functionDec;
  p->pos  =pos;
  p->u.function.name   = name;
  p->u.function.params = params;
  p->u.function.result = result;
  p->u.function.body   = body;
  return p;
}

A_decList A_DecList(A_dec head, A_decList tail)
{
  A_decList p = checked_malloc(sizeof(*p));
  p->head=head;
  p->tail=tail;
  return p;
}

A_dec A_TypeDec(A_pos pos, S_symbol name, A_ty ty)
{
  A_dec p = checked_malloc(sizeof(*p));
  p->kind = A_typeDec;
  p->pos  = pos;
  p->u.type.name = name;
  p->u.type.ty = ty;
  return p;
}

A_efield A_Efield(S_symbol name, A_exp exp)
{
  A_efield p = checked_malloc(sizeof(*p));
  p->name=name;
  p->exp=exp;
  return p;
}

A_efieldList A_EfieldList(A_efield head, A_efieldList tail)
{
  A_efieldList p = checked_malloc(sizeof(*p));
  p->head=head;
  p->tail=tail;
  return p;
}
